/** \file
 \brief Simulation Frame.
 */

#ifndef FASTMD_FRAME_INCLUDED
#define FASTMD_FRAME_INCLUDED 1

#include "core/vectors.hpp"
#include "yocto/ios/istream.hpp"

namespace FastMD 
{
	class Frame : public Object
	{
	public:
		static const size_t POSITIONS     = 0; //!< r->data = inv_mass
		static const size_t VELOCITIES    = 1; //!< v->data = mass
		static const size_t ACCELERATIONS = 2;
		static const size_t MIN_VECTORS   = 3;
		
		//! default constructor.
		Frame( const size_t num_vectors, size_t num_vertices ) ;
		
		//! default destrutor, release all.
		virtual ~Frame() throw();
		
		inline Vector       & operator[]( size_t index ) throw()       { assert(index<vectors); return vector_[index]; }
		inline const Vector & operator[]( size_t index ) const throw() { assert(index<vectors); return vector_[index]; }
		
		const size_t vectors;    //!< number or vectors
		const size_t particles;  //!< number of particles
		const V3D    box;        //!< current box
		const V3D    ibox;       //!< current reciprocal box
		PBC_Proc     pbc_r;      //!< for position
		PBC_Proc     pbc_f;      //!< for forces
		Real         V;          //!< current potential
		Real         K;          //!< current kinetic energy
		Real         W;          //!< current virial
		
		void set_box( const V3D &b ) throw();   //!< set box and ibox, NO RESCALING !!
		void rescale( const V3D &b ) throw();   //!< set box and ibox, WITH RESCALING !!
		void forces_to_accelerations() throw(); //!< multiply all accelerations by positions.data (inv_mass)
		void update_K() throw();                //!< recompute current Kinetic Energy
		void initialize_velocities( const Real temperature ) throw(); //!< Maxwell-Boltzman with zero linear momentum
		void thermal_friction(); //!< add thermal friction for isothermal simulation
		void thermal_update_K( const Real K_current ) throw(); //!< modify {v_i} with K_current to this->K
		void save( const string &filename, const Real t, bool append ) const;
		static Frame *load( ios::istream &, Real &t, const size_t num_vectors=0);
		
	private:
		Vector      *vector_;
		void release( size_t n ) throw();
		YOCTO_DISABLE_COPY_AND_ASSIGN(Frame);
	};
	
}

#endif
